package br.com.foxinline.manager.criar;

import br.com.foxinline.enums.EstadoCivil;
import br.com.foxinline.enums.Relatorio;
import br.com.foxinline.enums.TipoDocumento;
import br.com.foxinline.manager.generico.ManagerPesquisarGenerico;
import br.com.foxinline.modelo.Anexo;
import br.com.foxinline.modelo.Endereco;
import br.com.foxinline.modelo.Imovel;
import br.com.foxinline.modelo.Proprietario;
import br.com.foxinline.servico.AnexoServico;
import br.com.foxinline.servico.EnderecoServico;
import br.com.foxinline.servico.ImovelServico;
import br.com.foxinline.servico.ProprietarioServico;
import br.com.foxinline.servico.UsuarioServico;
import br.com.foxinline.util.ArquivoUtilitario;
import br.com.foxinline.util.Caracter;
import br.com.foxinline.util.Msg;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ejb.EJBAccessException;
import javax.ejb.EJBException;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import org.primefaces.context.RequestContext;
import org.primefaces.event.FileUploadEvent;

/**
 *
 * @author laverson
 */
@ManagedBean
@ViewScoped
public class ManagerProprietario extends ManagerPesquisarGenerico<Proprietario> {

    @EJB
    ProprietarioServico proprietarioServico;
    @EJB
    EnderecoServico enderecoService;
    @EJB
    ImovelServico imovelService;
    @EJB
    UsuarioServico usuarioServico;
    @EJB
    AnexoServico anexoServico;
    private Proprietario proprietario;
    private Proprietario proprietarioSalvo;
    private Proprietario pesquisarProprietario;
    private Proprietario deleteProprietario;
    private List<Proprietario> proprietarios;
    private List<Imovel> imoveis;
    private String vProprietario;
    private String eProprietario;
    private boolean renderInputsCpf;
    private Endereco enderecoClone;
    private Proprietario conjuge;
    private Proprietario conjugeAntigo;
    private boolean readonly;
    private Anexo anexo;
    private List<Anexo> anexosRemover;
    private ArquivoUtilitario arquivoUtilitario;
    private int indexAnexo;

    @Override
    public void init() {

        setServico(proprietarioServico);

        this.arquivoUtilitario = new ArquivoUtilitario();

        this.proprietario = new Proprietario();
        this.proprietario.setTipoDocumento(TipoDocumento.CPF);
        this.proprietario.setEndereco(new Endereco());
        this.proprietario.setAnexos(new ArrayList<Anexo>());

        this.pesquisarProprietario = new Proprietario();
        this.pesquisarProprietario.setTipoDocumento(TipoDocumento.CPF);

        this.renderInputsCpf = true;
        this.conjugeAntigo = new Proprietario();
        initConjuge();

        this.readonly = false;

        this.anexo = new Anexo();

        this.anexosRemover = new ArrayList<Anexo>();

        Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap();
        this.vProprietario = params.get("vProprietario");
        this.eProprietario = params.get("eProprietario");
        paramPost();
    }

    public void paramPost() {
        try {
            if (this.vProprietario != null) {

                this.readonly = true;

                this.proprietario = proprietarioServico.find(Long.parseLong(this.vProprietario));

                if (this.proprietario.getEndereco() == null) {
                    this.proprietario.setEndereco(new Endereco());
                } else {
                    this.proprietario.setEndereco(enderecoService.find(this.proprietario.getEndereco().getId()));
                }

                this.imoveis = imovelService.findImovelProprietario(this.proprietario);

                if (this.proprietario.getTipoDocumento() == null || this.proprietario.getTipoDocumento().equals(TipoDocumento.CPF)) {
                    this.renderInputsCpf = true;
                } else {
                    this.renderInputsCpf = false;
                }
            } else if (this.eProprietario != null || this.proprietario.getId() != null) {

                if (this.eProprietario != null) {
                    this.proprietario = proprietarioServico.find(Long.parseLong(this.eProprietario));
                } else if (this.proprietario.getId() != null) {
                    this.proprietario = proprietarioServico.find(this.proprietario.getId());
                }

                if (this.proprietario.getEndereco() == null) {
                    this.proprietario.setEndereco(new Endereco());
                    this.enderecoClone = new Endereco();
                } else {
                    this.enderecoClone = this.proprietario.getEndereco().getClone();
                }

                this.imoveis = imovelService.findImovelProprietario(this.proprietario);

                if (this.proprietario.getTipoDocumento() == null || this.proprietario.getTipoDocumento().equals(TipoDocumento.CPF)) {
                    this.renderInputsCpf = true;
                } else {
                    this.renderInputsCpf = false;
                }
            }

            if (this.proprietario.getConjuge() != null) {
                this.conjugeAntigo = this.proprietario.getConjuge();
            }
        } catch (Exception ex) {
            System.err.println(ex);
        }
    }

    public List<SelectItem> tipoDocumentoList() {
        List<SelectItem> items = new ArrayList<SelectItem>();
        for (TipoDocumento tipo : TipoDocumento.values()) {
            items.add(new SelectItem(tipo.getTipo(), tipo.getNome()));
        }
        return items;
    }

    public void save() {
        try {

            if (proprietarioServico.salvar(this.proprietario)) {
                this.proprietarioSalvo = this.proprietario;
                init();

                Msg.messagemInfo(Msg.SuccessFull);

                RequestContext.getCurrentInstance().execute("dlgProp.hide()");
            } else {
                Msg.messagemError(Msg.Failure);
            }

        } catch (Exception e) {
            System.err.println(e);
            Msg.messagemError(Msg.Failure);
        }
    }

    public void saveConjuge() {
        try {

            if (proprietarioServico.salvar(this.conjuge)) {
                this.proprietario.setConjuge(this.conjuge);
                this.proprietario.setEstadoCivil(EstadoCivil.CASADO);

                initConjuge();

                RequestContext.getCurrentInstance().execute("dlgProprietario.hide()");
            }

        } catch (Exception e) {
            System.err.println(e);
            Msg.messagemError(Msg.Failure);
        }
    }

    @Override
    public void pesquisar() {
        this.pesquisarProprietario.setCpf(Caracter.removecaracter(this.pesquisarProprietario.getCpf()));
        this.pesquisarProprietario.setCnpj(Caracter.removecaracter(this.pesquisarProprietario.getCnpj()));

        this.entidadePesquisar = this.pesquisarProprietario;

        getSearchResults().setFirst(0);
        onLoadModel();
    }

    public void atualizar() {
        try {
            if (this.proprietario.getConjuge() != null && this.proprietario.getConjuge().getId() != null
                    && this.proprietario.getId().equals(this.proprietario.getConjuge().getId())) {

                Msg.messagemError("Este proprietário não pode ser cônjuge dele mesmo."
                        + " Por favor, selecione outro cônjuge !");

            } else if (this.conjugeAntigo != null && this.proprietario.getConjuge() != null
                    && !this.conjugeAntigo.equals(this.proprietario.getConjuge())
                    && this.proprietario.getConjuge().getEstadoCivil() != null
                    && this.proprietario.getConjuge().getEstadoCivil().equals(EstadoCivil.CASADO)) {

                Msg.messagemError("O cônjuge selecionado já está casado !");
            } else {

                if (!this.enderecoClone.equals(this.proprietario.getEndereco())) {

                    this.proprietario.getEndereco().setUsuarioAtualizacao(usuarioServico.getCurrentUser());
                    this.proprietario.getEndereco().setDataAtualizacao(new Date());

                } else if (this.enderecoClone.equals(new Endereco())) {
                    this.proprietario.setEndereco(null);
                }

                if (!this.anexosRemover.isEmpty()) {
                    anexoServico.delete(this.anexosRemover);
                }

                if ((this.proprietario.getEstadoCivil() != null && !this.proprietario.getEstadoCivil().equals(EstadoCivil.CASADO)
                        && !this.proprietario.getEstadoCivil().equals(EstadoCivil.UNIAO_ESTAVEL))) {

                    if (this.proprietario.getConjuge() != null) {

                        this.proprietario.getConjuge().setEstadoCivil(EstadoCivil.SOLTEIRO);
                        this.proprietario.getConjuge().setConjuge(null);
                        proprietarioServico.update(this.proprietario.getConjuge());
                        this.proprietario.setConjuge(null);
                    }

                } else if ((this.proprietario.getEstadoCivil() != null && !this.proprietario.getEstadoCivil().equals(EstadoCivil.CASADO)
                        && !this.proprietario.getEstadoCivil().equals(EstadoCivil.UNIAO_ESTAVEL))
                        && (this.conjugeAntigo != null && this.proprietario.getConjuge() != null
                        && !this.conjugeAntigo.equals(this.proprietario.getConjuge()))) {

                    if (this.proprietario.getConjuge() != null) {

                        this.proprietario.getConjuge().setEstadoCivil(EstadoCivil.SOLTEIRO);
                        this.proprietario.getConjuge().setConjuge(null);
                        proprietarioServico.update(this.proprietario.getConjuge());
                        this.proprietario.setConjuge(null);
                    }

                } else {
                    atualizarConjuge();
                }

                proprietarioServico.update(this.proprietario);

                this.proprietario = this.proprietarioServico.find(this.proprietario.getId());

                if (this.proprietario.getConjuge() != null && this.proprietario.getConjuge().getId() != null) {
                    this.proprietario.setConjuge(proprietarioServico.find(this.proprietario.getConjuge().getId()));
                }

                this.conjugeAntigo = this.proprietario.getConjuge();

                if (this.proprietario.getEndereco() == null) {
                    this.proprietario.setEndereco(new Endereco());
                }

                Msg.messagemInfo(Msg.SuccessFull);
            }
        } catch (Exception e) {
            System.err.println(e);
            Msg.messagemError(Msg.Failure);
        }
    }

    @Override
    public void limpar() {
        this.pesquisarProprietario = new Proprietario();
        this.pesquisarProprietario.setTipoDocumento(TipoDocumento.CPF);
    }

    @Override
    public void remover() {
        try {
            proprietarioServico.delete(this.deleteProprietario);
        } catch (EJBAccessException e) {
            Msg.messagemWarn(Msg.PermissaoNegada);
        } catch (EJBException e) {
            Exception causedByException = e.getCausedByException();
            if (!(causedByException instanceof javax.validation.ConstraintViolationException)) {
                Msg.messagemWarn("Proprietário não pode ser removido pois existe pelo menos um imóvel em seu nome !");
            }
        }

        pesquisar();
    }

    public void existeEndereco() {
        Endereco endereco;
        if (this.eProprietario != null) {
            endereco = this.enderecoService.existCep(this.proprietario.getEndereco());
            if (endereco != null) {
                this.proprietario.setEndereco(endereco);
            } else {
                this.proprietario.setEndereco(new Endereco());
            }
        } else if (this.vProprietario != null) {
            endereco = this.enderecoService.existCep(this.proprietario.getEndereco());
            if (endereco != null) {
                this.proprietario.setEndereco(endereco);
            } else {
                this.proprietario.setEndereco(new Endereco());
            }
        } else {
            endereco = enderecoService.existCep(this.proprietario.getEndereco());
            if (endereco != null) {
                this.proprietario.setEndereco(endereco);
            } else {
                this.proprietario.setEndereco(new Endereco());
            }
        }
    }

    public void existeEnderecoConjuge() {
        Endereco endereco = this.enderecoService.existCep(this.conjuge.getEndereco());
        if (endereco != null) {
            this.conjuge.setEndereco(endereco);
        } else {
            this.conjuge.setEndereco(new Endereco());
        }
    }

    public boolean isPessoaFisica() {

        if (this.proprietario.getTipoDocumento() == null) {
            this.proprietario.setTipoDocumento(TipoDocumento.CPF);
        }

        return this.proprietario.getTipoDocumento().equals(TipoDocumento.CPF);
    }

    public boolean isConjugePessoaFisica() {

        if (this.conjuge.getTipoDocumento() == null) {
            this.conjuge.setTipoDocumento(TipoDocumento.CPF);
        }

        return this.conjuge.getTipoDocumento().equals(TipoDocumento.CPF);
    }

    private void atualizarConjuge() {

        if (this.proprietario.getConjuge() != null) {

            this.proprietario.getConjuge().setConjuge(this.proprietario);
            this.proprietario.getConjuge().setEndereco(this.proprietario.getEndereco());
            this.proprietario.getConjuge().setEstadoCivil(EstadoCivil.CASADO);

            proprietarioServico.update(this.proprietario.getConjuge());
        }
    }

    public void adicionarAnexo(FileUploadEvent event) throws IOException {
        try {
            this.anexo = arquivoUtilitario.adicionarArquivo(event.getFile().getContents(), event.getFile().getFileName(), event.getFile().getContentType());
//            this.anexo.setNomeExibicao(event.getFile().getFileName());

            RequestContext.getCurrentInstance().execute("dlgAnexo.show()");

        } catch (FileNotFoundException ex) {
            System.err.println(ex);
            Logger.getLogger(ManagerCriarImovel.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SQLException ex) {
            System.err.println(ex);
            Logger.getLogger(ManagerCriarImovel.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Remove o anexo da lista de anexos que está sendo adicionado e remove o arquivo do diretório que foi gravado
     *
     * @param anexo
     */
    public void removerAnexo(Anexo anexo) {
        try {
            arquivoUtilitario.excluirArquivo(new File(anexo.getUrl() + anexo.getNome()));
            this.proprietario.getAnexos().remove(anexo);
        } catch (Exception e) {
            System.err.println(e);
            Msg.messagemError(Msg.Failure);
        }
    }

    /**
     * Habilita a edicao do nome e do tipo de anexo
     *
     * @param anexo
     */
    public void editarAnexo(Anexo anexo) {
        this.anexo = anexo;
        this.indexAnexo = this.proprietario.getAnexos().indexOf(anexo);
    }

    /**
     * Atualiza o nome de exibição e tipo de anexo do anexo que está sendo editado
     */
    public void atualizarAnexo() {
        this.proprietario.getAnexos().get(this.indexAnexo).setNomeExibicao(this.anexo.getNomeExibicao());
        this.proprietario.getAnexos().get(this.indexAnexo).setTipoAnexo(this.anexo.getTipoAnexo());
    }

    /**
     * Adiciona o anexo (this.anexo) a lista de anexos do imovel
     */
    public void adicionarAnexo() {
        this.proprietario.getAnexos().add(this.anexo);
        this.anexo = new Anexo();
    }

    public void cancelarAnexo() {
        this.anexo = new Anexo();
    }

    /**
     * Remove o arquivo (this.anexo) do diretório que foi gravado
     *
     * @param anexo
     */
    public void removerAnexo() {
        try {
            arquivoUtilitario.excluirArquivo(new File(this.anexo.getUrl() + this.anexo.getNome()));
            this.anexo = new Anexo();
        } catch (Exception e) {
            System.err.println(e);
            Msg.messagemError(Msg.Failure);
        }
    }

    public void removerAnexoConjuge(Anexo anexo) {
        try {
            arquivoUtilitario.excluirArquivo(new File(anexo.getUrl() + anexo.getNome()));
            this.conjuge.getAnexos().remove(anexo);
        } catch (Exception e) {
            System.err.println(e);
            Msg.messagemError(Msg.Failure);
        }
    }

    public void editarAnexoConjuge(Anexo anexo) {
        this.anexo = anexo;
        this.indexAnexo = this.conjuge.getAnexos().indexOf(anexo);
    }

    public void atualizarAnexoConjuge() {
        this.conjuge.getAnexos().get(this.indexAnexo).setNomeExibicao(this.anexo.getNomeExibicao());
        this.conjuge.getAnexos().get(this.indexAnexo).setTipoAnexo(this.anexo.getTipoAnexo());
    }

    public void adicionarAnexoConjuge() {
        this.conjuge.getAnexos().add(this.anexo);
        this.anexo = new Anexo();
    }

    public void initConjuge() {
        this.conjuge = new Proprietario();
        this.conjuge.setTipoDocumento(TipoDocumento.CPF);
        this.conjuge.setAnexos(new ArrayList<Anexo>());
        this.conjuge.setEndereco(new Endereco());
    }

    public boolean removerConjuge() {

        if (this.proprietario.getEstadoCivil() != null) {
            List<String> estadosCivis = new ArrayList<String>();

            estadosCivis.add(EstadoCivil.SOLTEIRO.name());
            estadosCivis.add(EstadoCivil.DIVORCIADO.name());
            estadosCivis.add(EstadoCivil.VIUVO.name());
            estadosCivis.add(EstadoCivil.SEPARADO_JUDICIALMETE.name());

            boolean result = !estadosCivis.contains(proprietario.getEstadoCivil().name());

//            if (!result) {
//                this.proprietario.setConjuge(null);
//            }

            return result;
        }

        return false;
    }

    public void relDeclaracao(String r) {
        HashMap<String, Object> parametros = new HashMap<String, Object>();
        if (!(this.proprietario.getNome() == null || this.proprietario.getNome().isEmpty())) {
            parametros.put("nome", this.proprietario.getNome());
        }
        if (!(this.proprietario.getCpf() == null || this.proprietario.getCpf().isEmpty())) {
            parametros.put("cpf", Caracter.addMask(this.proprietario.getCpf(), Caracter.cpfMask));
        }
        if (!(this.proprietario.getProfissao() == null || this.proprietario.getProfissao().isEmpty())) {
            parametros.put("profissao", this.proprietario.getProfissao());
        }

        if (!desabilitaDeclNegativaRendimento()) {
            parametros.put("conjuge", this.proprietario.getConjuge().getNome());
            parametros.put("assConjuge", this.proprietario.getConjuge().getNome());
        }

        parametros.put("data", new Date());
        proprietarioServico.relDeclaracao(parametros, Relatorio.valueOf(r));
    }

    public boolean habilitaDeclaracoes() {
        if (this.proprietario.getTipoDocumento() != null && this.proprietario.getTipoDocumento().equals(TipoDocumento.CNPJ)) {
            return false;
        }
        return true;
    }

    public boolean desabilitaDeclPropriedade() {
        if (imoveis != null && !imoveis.isEmpty() && imoveis.size() > 1) {
            return true;
        }
        return false;
    }

    public boolean desabilitaDeclNegativaRendimento() {
        if (this.proprietario.getEstadoCivil() == null
                || (this.proprietario.getEstadoCivil() != null && (this.proprietario.getEstadoCivil() != EstadoCivil.CASADO && this.proprietario.getEstadoCivil() != EstadoCivil.UNIAO_ESTAVEL))) {
            return true;
        }
        return false;
    }

    public Proprietario getProprietario() {
        return proprietario;
    }

    public void setProprietario(Proprietario proprietario) {
        this.proprietario = proprietario;
    }

    public Proprietario getPesquisarProprietario() {
        return pesquisarProprietario;
    }

    public void setPesquisarProprietario(Proprietario pesquisarProprietario) {
        this.pesquisarProprietario = pesquisarProprietario;
    }

    public Proprietario getDeleteProprietario() {
        return deleteProprietario;
    }

    public void setDeleteProprietario(Proprietario entity) {
        this.deleteProprietario = entity;
    }

    public List<Proprietario> getProprietarios() {
        return proprietarios;
    }

    public void setProprietarios(List<Proprietario> proprietarios) {
        this.proprietarios = proprietarios;
    }

    public List<Imovel> getImoveis() {
        return imoveis;
    }

    public void setImoveis(List<Imovel> imoveis) {
        this.imoveis = imoveis;
    }

    public boolean isRenderInputsCpf() {
        if (this.proprietario != null && this.proprietario.getId() != null) {
            return this.proprietario.getTipoDocumento().equals(TipoDocumento.CPF);
        }

        return this.proprietario.getTipoDocumento().equals(TipoDocumento.CPF);
    }

    public void setRenderInputsCpf(boolean disableInputsCpf) {
        this.renderInputsCpf = disableInputsCpf;
    }

    public List<Proprietario> autocompleteConjuge(String query) {
        List<Proprietario> resultado = proprietarioServico.autocompletePessoaFisica(query);

        for (Proprietario p : resultado) {
            if (p.getId().equals(this.proprietario.getId())) {
                resultado.remove(p);
                break;
            }
        }

        return resultado;
    }

    public boolean isReadonly() {
        return readonly;
    }

    public void setReadonly(boolean readonly) {
        this.readonly = readonly;
    }

    public Anexo getAnexo() {
        return anexo;
    }

    public void setAnexo(Anexo anexo) {
        this.anexo = anexo;
    }

    public Proprietario getConjuge() {
        return conjuge;
    }

    public void setConjuge(Proprietario conjuge) {
        this.conjuge = conjuge;
    }

    public Proprietario getProprietarioSalvo() {
        return proprietarioSalvo;
    }

    public void setProprietarioSalvo(Proprietario proprietarioSalvo) {
        this.proprietarioSalvo = proprietarioSalvo;
    }
}
